import datetime
import hashlib
import json
import os
import sys
import time
from time import sleep

import requests
import warnings
from requests.packages import urllib3

import ksdemo
from Smtp import Stmp
from Log import Logger


class Library(object):

    def __init__(self, username, password, spaceId, area, from_addr, smtp_pwd, to_addr):
        self.max_try = 9999
        self.from_addr = from_addr
        self.smtp_pwd = smtp_pwd
        self.to_addr = to_addr
        self.username = username
        self.password = hashlib.md5(password.encode(encoding='UTF-8')).hexdigest()
        self.spaceId = spaceId
        self.area = area
        self.session = requests.session()
        self.code = ''
        self.segment = ''
        self.access_token = ''
        self.userid = ''
        self.php_session = ''
        self.author = ''  # 每日一言
        self.msg_one_day = ''
        self.today = datetime.date.today()
        self.tomorrow = self.today + datetime.timedelta(days=1)
        self.occur_time = str(self.today) + " 5:59:40"
        self.compare_time = datetime.datetime.strptime(self.occur_time, "%Y-%m-%d %H:%M:%S")
        self.cookies = {
            'PHPSESSID': '',
            'redirect_url': '%2Fhome%2Fweb%2Fseat%2Farea%2F1',
            'access_token': '',
            'userid': '',
            'user_name': '',
            'expire': ''
        }
        self.headers = {
            'Accept': 'application/json, text/javascript, */*; q=0.01',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,zh-TW;q=0.5',
            'Connection': 'keep-alive',
            'Referer': 'https://zwyy.tsg.zzife.xiaoyuanling.com/home/web/seat/area/1',
            'Sec-Fetch-Dest': 'empty',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-Site': 'same-origin',
            'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Mobile Safari/537.36',
            'X-Requested-With': 'XMLHttpRequest',
            'sec-ch-ua': '"Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"',
            'sec-ch-ua-mobile': '?1',
            'sec-ch-ua-platform': '"Android"',
        }

    # 每日一言
    def one_word_day(self):
        code = '000'
        try:
            while code != '200':
                response = requests.session().get('https://saying.api.azwcl.com/saying/get')
                response.encoding = 'utf-8'
                jsobj = json.loads(response.content)
                code = str(jsobj['code'])
                self.author = str(jsobj['data']['author'])
                self.msg_one_day = str(jsobj['data']['content'])
        except Exception as e:
            code = e
        return code

    # 创建 phpsession
    def creat_session_php(self):
        response = self.session.post('https://zwyy.tsg.zzife.xiaoyuanling.com/api.php/login', cookies=self.cookies,
                                     headers=self.headers)
        response.encoding = 'utf-8'
        self.php_session = response.cookies.get("PHPSESSID")
        self.cookies = {
            'PHPSESSID': self.php_session,
            'redirect_url': '%2Fhome%2Fweb%2Fseat%2Farea%2F1',
            'access_token': '',
            'userid': '',
            'user_name': '',
            'expire': ''
        }
        return self.php_session

    # 识别验证码
    def verify_code(self, KSC_name, KSC_pwd):
        verify_code_url = 'https://zwyy.tsg.zzife.xiaoyuanling.com/api.php/check'
        code_response = self.session.get(url=verify_code_url, cookies=self.cookies, headers=self.headers, verify=False)
        with open('verify.png', mode='wb') as f:
            f.write(code_response.content)

        Ks95man = ksdemo.KSClient()
        ks_ok = Ks95man.GetTaken(KSC_name, KSC_pwd)
        if ks_ok:
            # 获取成功,taken获取一次就可以了，taken 生成后如果不用参数"isref=1"刷新，就一直不会变。如果写死在您的软件中，就要慎用"isref=1"，否则您之前写死的软件都要改taken。
            # 开始识别
            # 获取文件二进制流
            self.code = Ks95man.PostPic('verify.png', 2)
            log.info(self.code)
            # 识别报错
        return Ks95man.ReportError(88)

    # 登录
    def login(self):
        data = {
            'username': self.username,
            'password': self.password,
            'verify': self.code
        }
        response = self.session.post('https://zwyy.tsg.zzife.xiaoyuanling.com/api.php/login', cookies=self.cookies,
                                     headers=self.headers,
                                     data=data, verify=False)
        response.encoding = 'utf-8'
        jsobj = json.loads(response.text)

        # 登录状态 0 为登录失败 1 成功
        status = jsobj['status']
        msg = jsobj['msg']
        userid = response.cookies.get('userid')
        access_token = response.cookies.get('access_token')
        self.access_token = access_token
        self.userid = userid
        expire = response.cookies.get('expire')
        user_name = response.cookies.get('user_name')
        self.cookies = {
            'PHPSESSID': self.php_session,
            'redirect_url': '%2Fhome%2Fweb%2Fseat%2Farea%2F1',
            'access_token': access_token,
            'userid': userid,
            'user_name': user_name,
            'expire': expire
        }
        return msg

    # 获取第二天的segment参数
    def get_segment(self):
        msg = ''
        retry_segment = 0
        status = 0
        data = {
            'day': self.tomorrow,
            'area': self.area
        }

        while status != 1:
            retry_segment = retry_segment + 1
            if retry_segment >= self.max_try:
                break
            response = self.session.get(
                url='https://zwyy.tsg.zzife.xiaoyuanling.com/api.php/space_time_buckets',
                params=data,
                cookies=self.cookies,
                headers=self.headers,
                verify=False)
            response.encoding = 'utf-8'
            jsobj = json.loads(response.text)
            status = int(jsobj['status'])
            msg = jsobj['msg']
            if status == 1:
                segment = jsobj['data']['list']
                self.segment = segment[0]['bookTimeId']

        return msg

    # 预约指定位置
    def reserve_seat(self):
        retry_seat = 0
        status = 0
        msg = []
        data_bookApi = {
            'access_token': self.access_token,
            'segment': self.segment,
            'type': '1',
            'operateChannel': '2',
            'userid': self.userid
        }

        while status != 1:
            retry_seat = retry_seat + 1
            if retry_seat > self.max_try:
                log.error("预约位置—max_try次数使用完")
                break
            bookApi = 'https://zwyy.tsg.zzife.xiaoyuanling.com/api.php/spaces/' + self.spaceId + '/book'
            code_response = self.session.get(url=bookApi,
                                             cookies=self.cookies,
                                             headers=self.headers,
                                             params=data_bookApi,
                                             verify=False)
            code_response.encoding = 'utf-8'
            jsobj = json.loads(code_response.text)
            status = int(jsobj['status'])
            msg = jsobj['msg']
            if status == 0:
                if msg == "该空间当前状态不可预约":
                    # smtp = Stmp(from_addr, to_addr, smtp_pwd)
                    # context = "<div>预约测试<br>" + "学号：" + username + "<br>error:" + mail_msg + "</div>"
                    # smtp.sent_mail(context)
                    spaceId = int(self.spaceId) + 1
                    self.spaceId = str(spaceId)
                    log.info(msg)
                    log.info("自动预约下一个座位{" + str(spaceId) + "}")
                    sleep(1)
                if msg == "当前用户在该时段已存在预约，不可重复预约":
                    break
                if msg == "由于您长时间未操作，正在重新登录":
                    break
                if msg == "预约失败，系统开始预约时间为：06:00" or msg == "预约失败，系统开始预约时间为：12:00":
                    now_time = datetime.datetime.now()
                    compare_time = datetime.datetime.strptime(self.occur_time, "%Y-%m-%d %H:%M:%S")
                    now_time_sleep = time.mktime(now_time.timetuple())
                    occur_sleep = time.mktime(compare_time.timetuple())
                    if now_time_sleep < occur_sleep:
                        seconds_sleep = occur_sleep - now_time_sleep
                        log.info(msg + "-执行-sleep：" + str(seconds_sleep) + "s")
                        sleep(seconds_sleep)
                else:
                    sleep(1)
            if status == 1:
                seat = jsobj['data']['list']
                no_today = seat['no']
                seat = seat['spaceInfo']['name']
                now_time = datetime.datetime.now()
                head = """
                                <!DOCTYPE html>
                                    <html lang="ch">
                                    <head>
                                        <meta charset="UTF-8">
                                    </head>
                        """
                body = """
                <body>
                <div>
                    <div>
                        <div>
                            <div style="
                            background: rgba(150,214,246,0.56);
                            box-shadow: 0 2px 8px 0 rgba(215,121,121,0.2);
                            border-radius: 20px;
                            margin: 50px auto;
                            max-width: 500px;
                            overflow: hidden;
                            padding: 0 35px !important;
                            padding-left: 30px !important;
                            font-family: Helvetica Neue, Arial, PingFang SC, Hiragino Sans GB, STHeiti, Microsoft YaHei, sans-serif;
                            -webkit-font-smoothing: antialiased;
                            color: #2b2b2b;
                            font-size: 14px;
                            line-height: 1.75">
                                <div style="color: #a2295f;font-size: 18px;">
                                    图书馆每日预约提醒
                                </div>

                                <div style="font-size: 2px;">
                                    <div style="text-align: right">
                                        <img src="https://rescdn.qqmail.com/node/wwqy/qymng/style/images/sass/independent/welcome_eml_logo.png"
                                             style="width: 34px; height: 24px;" onerror="" alt="https://gitee.com/shengxiadeshengxia/zzife_booker_library">
                                    </div>
                                </div>
                                <div style="color: #1b47a4;font-size: 18px;padding: 50px">
                                    预约成功
                                </div>
                                <div style=" position: relative;
                                padding: 20px 50px 0;
                                min-height: 216px;
                                word-break: break-all">
                                    <div>
                                        <div style="font-size: 15px;padding: 10px;text-align: center">
                                            学号：""" + username1 + """
                                        </div>
                                        <div style="font-size: 15px;padding: 10px;text-align: center">
                                            成功时间：""" + str(now_time)[0:19] + """
                                        </div>
                                        <div style="font-size: 15px;padding: 10px;text-align: center">
                                            预约日期：""" + str(self.tomorrow) + """
                                        </div>
                                        <div style="font-size: 15px;padding: 10px;text-align: center">
                                            当天预约第：""" + str(no_today)[8:] + """ 位
                                        </div>
                                        <div>
                                            <div style="margin-bottom: 10px;padding: 1px;">
                                                <div style="font-size:20px;color: red;text-align: center;font-weight:bold"> 你的座位为：""" + seat + """
                                                </div>
                                            </div>
                                        </div>
                                        <div style="font-size: 20px;padding: 10px;text-align: left">
                                            每日一言:
                                        </div>

                                        <div>
                                            <div style="margin-bottom: 10px;padding: 3px;text-align: center">
                                                <div>""" + self.msg_one_day + """</div>
                                            </div>
                                        </div>

                                        <div style="font-size: 10px;padding: 10px;text-align: end">
                                            ----""" + self.author + """
                                        </div>
                                    </div>
                                </div>

                                <div style="font-weight: 300;
                            font-size: 12px;
                            letter-spacing: .5px;
                            padding: 0 0 30px 50px;
                            margin-top: 60px"><a href="https://gitee.com/shengxiadeshengxia/zzife_booker_library">盛xia的盛夏</a>
                                </div>
                            </div>
                        </div>
                    </div><!--<![endif]-->
                </div>
                </body>
                        """

                context2 = head + body
                # context2 = "<div><h3>预约成功:  </h3><br>" + "预约成功时间：" + str(now_time)[
                #                                                      :19] + "<br>学号：" + username1 + "<br>预约时间：" + str(
                #     self.tomorrow) + "<br>当天预约第: " + str(no_today)[8:] + "位" + "<br> 座位：" + seat + "</div>"
                msg_smtp = smtp.sent_mail(context2)
                log.info(msg_smtp)
                log.info("预约成功,座位为{" + seat + "}")
                self.session.close()
            log.info(jsobj)
        return msg


if __name__ == '__main__':
    file = []
    config_name = 'userinfo.json'
    # determine if application is a script file or frozen exe
    if getattr(sys, 'frozen', False):
        application_path = os.path.dirname(sys.executable)
    elif __file__:
        application_path = os.path.dirname(__file__)
    config_path = os.path.join(application_path, config_name)
    urllib3.disable_warnings()
    warnings.filterwarnings("ignore")
    log = Logger(level="debug").logger
    if os.path.exists(config_name):
        with open(config_path, 'r', encoding='utf-8') as f:
            file = json.load(f)
        for info in file:
            username1 = info['username']
            password1 = info['password']
            spaceId1 = info['spaceId']
            area1 = info['area']
            from_addr1 = info['from_addr']
            to_addr1 = info['to_addr']
            smtp_pwd1 = info['smtp_pwd']
            ksc_name = info['KSC_name']
            ksc_pwd = info['KSC_pwd']
            smtp = Stmp(from_addr1, to_addr1, smtp_pwd1)
            booker = Library(username1, password1, spaceId1, area1, from_addr1, smtp_pwd1, to_addr1)
            statis_all = 0
            statis_very = 0
            statis_login = 0
            statis_segment = 0
            statis_seat = 0
            count = 0
            retry = 0
            mail_msg = ''
            while statis_all == 0:
                count = 0
                statis_very = 0
                statis_segment = 0
                statis_seat = 0
                retry = retry + 1
                if retry > booker.max_try:
                    break
                log.info("用户：{" + booker.username + "}")
                while statis_very == 0:
                    try:
                        log.info("获取每日一言")
                        msg = booker.one_word_day()
                        if msg != '200':
                            log.error("每日一言-获取失败")
                            break
                        log.info("获取PHPSESSUIN")
                        booker.creat_session_php()
                        log.info("获取验证码")
                        mail_msg = booker.verify_code(ksc_name, ksc_pwd)
                        log.info(mail_msg)
                        statis_very = 1
                        count = count + 1
                        sleep(1)
                        log.info("登录")
                        mail_msg = booker.login()
                        log.info(mail_msg)
                        if mail_msg != "登陆成功":
                            break
                        count = count + 1
                        sleep(1)
                    except Exception as e:
                        mail_msg = str(e)
                        log.error(mail_msg)
                while statis_segment == 0:
                    if count != 2:
                        break
                    try:
                        log.info("获取segment")
                        mail_msg = booker.get_segment()
                        log.info(mail_msg)
                        if mail_msg != "获取可预约时间段":
                            break
                        statis_segment = 1
                        count = count + 1
                        sleep(1)
                    except Exception as e:
                        mail_msg = str(e)
                        log.error(mail_msg)
                while statis_seat == 0:
                    if count != 3:
                        break
                    try:
                        log.info("预约ing")
                        mail_msg = booker.reserve_seat()
                        log.info(mail_msg)
                        if mail_msg == "由于您长时间未操作，正在重新登录":
                            break
                        statis_seat = 1
                        count = count + 1
                        sleep(1)
                    except Exception as e:
                        mail_msg = str(e)
                        log.error(mail_msg)
                if count == 4:
                    statis_all = 1
            # 最大失败次数达到
            if statis_all == 0:
                log.error("最大失败次数达到")
                context1 = "<div>预约失败<br>" + "学号：" + username1 + "<br>error:" + mail_msg + "</div>"
                msg = smtp.sent_mail(context1)
                log.info(msg)
            log.info("##########################################")
    else:
        log.error("json文件不存在")
        print("json文件不存在")
